package com.snow.datasource.healths;

import com.snow.datasource.properties.SnowFlakeProperties;
import com.snow.datasource.provider.ISnowProvider;
import com.snow.datasource.route.SnowRoutingDataSource;
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.IncorrectResultSetColumnCountException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.JdbcUtils;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 主从模式健康监测
 *
 * @Description
 * @Author fanxl
 * @Date 2020/12/24
 **/
@Data
public class MasterSlaveHealth extends AbstractHealthIndicator implements InitializingBean {
    /**
     * 属性配置
     */
    @Autowired
    private SnowRoutingDataSource snowRoutingDataSource;

    public Map<String, Boolean> dbHealth = new ConcurrentHashMap<>();

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        Map<String, DataSource> dataSourceMap = snowRoutingDataSource.getDataSourceMap();
        for (String key : dataSourceMap.keySet()) {
            DataSource dataSource = dataSourceMap.get(key);
            Integer result = 0;
            try {
                result = query(dataSource);
                builder.withDetail(key, "正常").status("200");
            } catch (Exception e) {
                builder.withDetail(key, "失败");
            } finally {
                if (result == 1) {
                    dbHealth.put(key, Boolean.TRUE);
                }else{
                    dbHealth.remove(key);
                }
            }
        }
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, DataSource> dataSourceMap = snowRoutingDataSource.getDataSourceMap();
        for (String key : dataSourceMap.keySet()) {
            DataSource dataSource = dataSourceMap.get(key);
            Integer result = 0;
            try {
                result = query(dataSource);
            } finally {
                if (result == 1) {
                    dbHealth.put(key, Boolean.TRUE);
                }else{
                    dbHealth.remove(key);
                }
            }
        }
    }
    private Integer query(DataSource dataSource) {
        List<Integer> results = new JdbcTemplate(dataSource).query("SELECT 1", new RowMapper<Integer>() {

            @Override
            public Integer mapRow(ResultSet resultSet, int i) throws SQLException {
                ResultSetMetaData metaData = resultSet.getMetaData();
                int columns = metaData.getColumnCount();
                if (columns != 1) {
                    throw new IncorrectResultSetColumnCountException(1, columns);
                }
                return (Integer) JdbcUtils.getResultSetValue(resultSet, 1, Integer.class);
            }
        });
        return DataAccessUtils.requiredSingleResult(results);
    }
}
